package com.bolt.support.spring.jpa.jpql;


import com.bolt.support.query.toolkit.JPAUtil;

import javax.annotation.Nullable;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import javax.persistence.Query;
import java.util.function.Consumer;

/**
 * Created by Administrator on 2020/9/9.
 */
public class JPAUpdate implements JPQLUpdate<JPAUpdate> {


    private final EntityManager entityManager;

    protected final QueryMetadata queryMetadata;

    @Nullable
    private LockModeType lockMode;

    public JPAUpdate(EntityManager entityManager, EntityClause entity) {
        this.entityManager = entityManager;
        this.queryMetadata = new DefaultQueryMetadata(entityManager);
        this.queryMetadata.addJoin(JoinType.DEFAULT, entity);
    }

    @Override
    public <E> JPAUpdate set(ColumnClause<E> columnClause, E value) {
        if (value != null) {
            this.queryMetadata.addUpdates(columnClause, Clauses.of(columnClause, value));
        } else {
            this.queryMetadata.addUpdates(columnClause, ParamClause.Null);
        }
        return this;
    }

    @Override
    public JPAUpdate set(StitchClause stitchClause) {
        this.queryMetadata.addUpdates(stitchClause);
        return this;
    }

    public JPAUpdate setLockMode(LockModeType lockMode) {
        this.lockMode = lockMode;
        return this;
    }

    @Override
    public long execute() {
        JPQLBuilder builder = new JPQLBuilder();
        String queryString = builder.renderUpdate(queryMetadata);
        Query query = entityManager.createQuery(queryString);
        JPAUtil.setParameter(query, queryMetadata.getParam());
        if (lockMode != null) {
            query.setLockMode(lockMode);
        }
        return query.executeUpdate();
    }

    @Override
    public JPAUpdate where(CompareClause clause) {
        this.queryMetadata.setWhere(clause.render(false));
        return this;
    }

    @Override
    public JPAUpdate where(Consumer<CompareClause> consumer) {
        CompareClause instance = new CompareClause();
        consumer.accept(instance);
        queryMetadata.setWhere(instance.render(false));
        return this;
    }
}

 